﻿using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using SharpCapture;
using SharpCapture.Interface;

namespace WordEdit
{
    public partial class VedioFrom : Form
    {
        #region 变量
        private int nAudioDataLen = 0;
        private ICameraCapture camera = null;
        private IScreenCapture screen = null;
        private ISoundcardCapture soundcard = null;
        private IMicrophoneCapture microphone = null;
        private IMixer mixer = null;

        //下面是wav文件生成类
        private WavHelper soundcardWav = null;
        private WavHelper microphoneWav = null;
        private WavHelper mixedWav = null;
        private Size picSize;
        #endregion

        public VedioFrom()
        {
            InitializeComponent();
        }


        #region 事件
        private void typeSelect_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (typeSelect.SelectedIndex == 0)
            {
                ShowCameraArg(true);
            }
            else
            {
                ShowCameraArg(false);
            }
        }

        private void VedioFrom_Load(object sender, EventArgs e)
        {

            //注意!!
            //在调用SharpCapture的其他方法之前，请务必调用本方法设置授权Key，否则会抛出异常
            KeyMgr.SetKey("Test");

            typeSelect.SelectedIndex = 0;
        }

        private void start_Click(object sender, EventArgs e)
        {
            try
            {
                picSize = videoBox.Size;
                lblStatus.Text = "";
                if (this.typeSelect.SelectedIndex == 0)
                {
                    //摄像头采集
                    camera = CaptureFactory.GetCameraCapture(0, new Size(int.Parse(this.widthInput.Text), int.Parse(this.heightInput.Text)),
                                    30);

                    //注册采集到帧图片的事件，在该事件函数中得到采集到的帧图片
                    camera.FrameImageCaptured += new SGDelegate<Bitmap>(CameraImageCaptured);

                    //开始采集
                    camera.Start();
                }
                else if (this.typeSelect.SelectedIndex == 1)
                {
                    //屏幕画面采集
                    screen = CaptureFactory.GetScreenCapture(20, true);

                    //注册采集到屏幕画面的事件，该事件函数中可以得到采集到的帧图片
                    screen.FrameImageCaptured += new SGDelegate<Bitmap>(ScreenImageCaptured);

                    //开始采集
                    screen.Start();
                }
                else if (this.typeSelect.SelectedIndex == 2)
                {
                    //麦克风采集，默认采集第一个麦克风
                    microphone = CaptureFactory.GetMicrophoneCapture(0);

                    //注册采集到声音数据的事件，每当采集到声音数据，就通过该事件上报
                    microphone.AudioDataCaptured += new SGDelegate<byte[]>(MicrophoneAudioDataCaptured);


                    //采集开始前，先初始化麦克风wav文件写入器
                    string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "microphone.wav");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    microphoneWav = new WavHelper(path, microphone.SampleRate, (short)microphone.ChannelCount);


                    //开始采集
                    microphone.Start();
                }
                else if (this.typeSelect.SelectedIndex == 3)
                {
                    //声卡数据采集
                    soundcard = CaptureFactory.GetSoundcardCapture();

                    //注册采集到声音数据的事件，每当采集到声音数据，就通过该事件上报
                    soundcard.AudioDataCaptured += new SGDelegate<byte[]>(SoundcardAudioDataCaptured);

                    //采集开始前，先初始化声卡wav文件写入器
                    string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "soundcard.wav");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    soundcardWav = new WavHelper(path, soundcard.SampleRate, (short)soundcard.ChannelCount);

                    //开始采集
                    soundcard.Start();
                }
                else
                {
                    //麦克风采集，默认采集第一个麦克风
                    microphone = CaptureFactory.GetMicrophoneCapture(0);

                    //声卡数据采集
                    soundcard = CaptureFactory.GetSoundcardCapture();

                    //创建混音器
                    mixer = CaptureFactory.GetAudioMixter(microphone, soundcard, SoundcardMixMode.DoubleChannel, true);

                    //采集开始前，先初始化混音wav文件写入器
                    string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mixed.wav");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    mixedWav = new WavHelper(path, mixer.OutputSampleRate, (short)mixer.OutputChannelCount);

                    //注册采集到声音数据的事件，每当采集到声音数据，就通过该事件上报
                    mixer.AudioMixed += new SGDelegate<byte[]>(MixedAudioDataCaptured);

                    //开始采集
                    microphone.Start();
                    soundcard.Start();
                }

                start.Enabled = false;
                stop.Enabled = true;
                typeSelect.Enabled = false;
                nAudioDataLen = 0;
                audioDataLable.Text = "0";
            }
            catch (Exception ee)
            {
                MessageBox.Show(ee.Message);
            }
        }

        private void stop_Click(object sender, EventArgs e)
        {
            //停止采集
            if (typeSelect.SelectedIndex == 0)
            {
                if (camera != null)
                {
                    camera.Stop();
                    camera = null;
                }
            }
            else if (typeSelect.SelectedIndex == 1)
            {
                if (screen != null)
                {
                    screen.Stop();
                    screen = null;
                }
            }
            else if (typeSelect.SelectedIndex == 2)
            {
                if (microphone != null)
                {
                    microphone.Stop();
                    microphone = null;

                    if (microphoneWav != null)
                    {
                        microphoneWav.Dispose();
                        lblStatus.Text = "录音成功!wav文件已保存到根目录下microphone.wav.";
                        microphoneWav = null;
                    }
                }
            }
            else if (typeSelect.SelectedIndex == 3)
            {
                if (soundcard != null)
                {
                    soundcard.Stop();
                    soundcard = null;

                    if (soundcardWav != null)
                    {
                        soundcardWav.Dispose();
                        lblStatus.Text = "录音成功!wav文件已保存到根目录下soundcard.wav.";
                        soundcardWav = null;
                    }
                }
            }
            else
            {
                if (microphone != null)
                {
                    microphone.Stop();
                    microphone = null;
                }

                if (soundcard != null)
                {
                    soundcard.Stop();
                    soundcard = null;
                }

                if (mixer != null)
                {
                    mixer.Dispose();
                    mixer = null;
                }

                if (mixedWav != null)
                {
                    mixedWav.Dispose();
                    lblStatus.Text = "录音成功!wav文件已保存到根目录下mixed.wav.";
                    mixedWav = null;
                }
            }




            this.stop.Enabled = false;
            this.start.Enabled = true;
            this.typeSelect.Enabled = true;
            audioDataLable.Text = "0";

            SGDelegate cb = new SGDelegate(Clear);
            cb.BeginInvoke(null, null);
        }

        private void VedioFrom_FormClosing(object sender, FormClosingEventArgs e)
        {

            stop_Click(null, null);
        }
        #endregion

        #region 功能
        /// <summary>
        /// 显示或者隐藏摄像头的分辨率设置UI
        /// </summary>
        /// <param name="bShow"></param>
        private void ShowCameraArg(bool bShow)
        {
            heightLabel.Visible = bShow;
            widthLabel.Visible = bShow;
            widthInput.Visible = bShow;
            heightInput.Visible = bShow;
        }

        /// <summary>
        /// 采集到画面
        /// </summary>
        /// <param name="img"></param>
        public void CameraImageCaptured(Bitmap img)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new SGDelegate<Bitmap>(CameraImageCaptured), img);
            }
            else
            {
                Bitmap old = (Bitmap)this.videoBox.BackgroundImage;
                this.videoBox.BackgroundImage = img;
                if (old != null)
                {
                    old.Dispose(); //立即释放不再使用的Bitmap，避免内存泄漏
                }
            }
        }

        /// <summary>
        /// 采集到麦克风的声音数据
        /// </summary>
        /// <param name="audioData">声音数据</param>
        public void MicrophoneAudioDataCaptured(byte[] audioData)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new SGDelegate<byte[]>(MicrophoneAudioDataCaptured), audioData);
            }
            else
            {
                //计数并显示
                nAudioDataLen += audioData.Length;
                audioDataLable.Text = nAudioDataLen.ToString();

                //写入麦克风的wav文件中
                if (microphoneWav != null)
                {
                    microphoneWav.WriteAudioData(audioData);
                }
            }
        }


        /// <summary>
        /// 采集到声卡的声音数据
        /// </summary>
        /// <param name="audioData">声音数据</param>
        public void SoundcardAudioDataCaptured(byte[] audioData)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new SGDelegate<byte[]>(SoundcardAudioDataCaptured), audioData);
            }
            else
            {
                //计数并显示
                nAudioDataLen += audioData.Length;
                audioDataLable.Text = nAudioDataLen.ToString();

                //写入声卡的wav文件中
                if (soundcardWav != null)
                {
                    soundcardWav.WriteAudioData(audioData);
                }
            }
        }

        public void MixedAudioDataCaptured(byte[] audioData)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new SGDelegate<byte[]>(MixedAudioDataCaptured), audioData);
            }
            else
            {
                //计数并显示
                nAudioDataLen += audioData.Length;
                audioDataLable.Text = nAudioDataLen.ToString();

                //写入混音后的wav文件中
                if (mixedWav != null)
                {
                    mixedWav.WriteAudioData(audioData);
                }
            }
        }

        /// <summary>
        /// 采集到屏幕画面
        /// </summary>
        /// <param name="img"></param>
        public void ScreenImageCaptured(Bitmap img)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new SGDelegate<Bitmap>(ScreenImageCaptured), img);
            }
            else
            {
                Bitmap old = (Bitmap)this.videoBox.BackgroundImage;
                this.videoBox.BackgroundImage = new Bitmap(img, picSize);
                if (old != null)
                {
                    old.Dispose(); //立即释放不再使用的Bitmap，避免内存泄漏
                }
            }
        }

        /// <summary>
        /// 清除最后一帧的图片
        /// </summary>
        private void Clear()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new SGDelegate(Clear));
            }
            else
            {
                this.videoBox.BackgroundImage = null;
                this.videoBox.Invalidate();
            }
        }

        #endregion

        private void VedioFrom_ClientSizeChanged(object sender, EventArgs e)
        {
            picSize = videoBox.Size;
        }
    }
}
